Skip to content

fix(commands): resolve --assignee to UUID in issues create/update#50

Merged
iamfj merged 3 commits into
nextfrom
fix/47-resolve-assignee-id
Feb 20, 2026
Merged

fix(commands): resolve --assignee to UUID in issues create/update#50
iamfj merged 3 commits into
nextfrom
fix/47-resolve-assignee-id

Conversation

@iamfj
Copy link
Copy Markdown
Member

@iamfj iamfj commented Feb 20, 2026

What

Fix for --assignee option on issues create and issues update failing with a GraphQL validation error when given a human-friendly name or email instead of a UUID.

Problem

The --assignee value was passed directly to input.assigneeId without resolution. Every other identifier option (--team, --project, --labels, --cycle, --status, --parent-ticket, --project-milestone) goes through a dedicated resolver, but --assignee was missing one, causing:

{"error": "GraphQL request failed: Argument Validation Error - assigneeId must be a UUID."}

Solution

  • Added resolveUserId() resolver (src/resolvers/user-resolver.ts) using LinearSdkClient, following the established resolver pattern
  • Lookup order: UUID passthrough → display name (case-insensitive) → email (case-insensitive)
  • Handles multipleMatchesError when name is ambiguous, notFoundError when no match exists
  • Wired resolver into both issues create and issues update commands

Testing

  • 5 resolver unit tests: UUID passthrough, name lookup, email fallback, not-found error, multiple-matches error
  • 5 command-level integration tests: verify resolveUserId is called with correct args and its UUID flows into createIssue/updateIssue for both name and email inputs, plus omitted-assignee cases
  • All 143 tests passing, build clean

Checklist

  • Bug resolved
  • Regression tests added
  • No side effects introduced

Closes #47

iamfj and others added 3 commits February 20, 2026 11:40
Resolves user identifiers (display name, email, or UUID) to UUIDs via
the Linear SDK, following the same pattern as existing resolvers.

Lookup order: UUID passthrough → display name (case-insensitive) →
email (case-insensitive). Throws multipleMatchesError when name is
ambiguous, notFoundError when no match exists.

Closes #47

Co-Authored-By: claude-opus-4-6 <noreply@anthropic.com>
The --assignee option was passed directly to assigneeId without
resolution, causing GraphQL validation errors when given a name or
email instead of a UUID. Wire both create and update through the new
resolveUserId resolver.

Closes #47

Co-Authored-By: claude-opus-4-6 <noreply@anthropic.com>
Add command-level tests that drive the CLI through Commander and
verify resolveUserId is called with the correct input and its result
flows into the service layer. Covers create with name, create with
email, update with name, and omitted-assignee cases.

Co-Authored-By: claude-opus-4-6 <noreply@anthropic.com>
@iamfj iamfj added the bug Something isn't working label Feb 20, 2026
@iamfj iamfj self-assigned this Feb 20, 2026
@iamfj iamfj merged commit 64dfac1 into next Feb 20, 2026
2 checks passed
@iamfj iamfj mentioned this pull request Feb 20, 2026
12 tasks
iamfj added a commit that referenced this pull request Apr 7, 2026
Replace the flat utils-based structure with a strict five-layer
architecture enforcing separation of concerns:

  CLI Input → Command → Resolver → Service → JSON Output

Clients:
- GraphQLClient: typed wrapper for raw GraphQL operations
- LinearSdkClient: wrapper for Linear SDK access

Common modules:
- context: CommandContext factory with createContext()
- errors: structured error helpers (notFoundError, etc.)
- identifier: UUID detection and identifier parsing
- output: typed outputSuccess/outputError functions
- types: shared type aliases derived from codegen types
- usage: DomainMeta system for self-documenting commands

Resolvers (human ID → UUID, using LinearSdkClient):
- team, project, label, status, issue, cycle, milestone, user

Services (business logic, using GraphQLClient):
- issue, document, attachment, file, comment, cycle, milestone,
  project, team, user, label, issue-relation, auth

Commands rewritten to delegate through layers:
- Rename embeds → files, project-milestones → milestones
- Merge search into list commands
- Add issue relation flags (--blocks, --blocked-by, --relates-to)
- Add cursor pagination (--after, --limit) to all list commands
- Add --assignee resolution by name or email
- Add encrypted token auth (login, status, logout)
- Add usage subcommand to every command group

Remove old utils/, queries/ directories and their tests.
Add comprehensive unit tests for all resolvers and services.

Closes #27, closes #43, closes #47
Refs #2, #3, #14, #16
Part of #45, incorporates #50, #53
@iamfj iamfj deleted the fix/47-resolve-assignee-id branch April 21, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant